rm(list = ls())
library("rstudioapi")
setwd(dirname(getActiveDocumentContext()$path))
# please make sure your working directory is set to this file location
wd = getwd()
library(dplyr)
library(tidyverse)
library(rENA)
library(plotly)
library(jsonlite)
library(ona)
library(tma)
library(magrittr)
library(readr)
library(ggplot2)
library(ggrepel)
library(ggfortify)
library(data.table)
library(superheat)
library(rjson)
library(RColorBrewer)
library(randomcoloR)
library(rlist)
library(webshot)
generate.ona.object <- function(data, unit.col, meta.col, codes){
output <- list()
f.units <- unit.col
ENA_UNIT <- rENA::merge_columns_c(f.units, cols = colnames(f.units));
# ENA_UNIT <- f.units
f.raw <- data
f.codes <- codes
dena_data = directedENA:::ena.set.directed(f.raw, f.units, NA, f.codes)
output.meta.data <- meta.col
dena_data$meta.data <- data.table::as.data.table(cbind(ENA_UNIT, output.meta.data))
for( i in colnames(dena_data$meta.data) ) {
set(dena_data$meta.data, j = i, value = rENA::as.ena.metadata(dena_data$meta.data[[i]]))
}
code_length <- length(dena_data$rotation$codes);
dena_data$rotation$adjacency.key <- data.table::data.table(matrix(c(
rep(1:code_length, code_length),
rep(1:code_length, each = code_length)),
byrow = TRUE, nrow = 2
))
directed.adjacency.vectors <- as.ena.matrix(data.table::as.data.table(data[, grep("V", colnames(data))]), "ena.connections")
# aren't these two the same thing
dena_data$connection.counts <- data.table::as.data.table(cbind(dena_data$meta.data, directed.adjacency.vectors))
dena_data$connection.counts = rENA::as.ena.matrix(x = dena_data$connection.counts, "ena.connections")
for (i in which(!rENA::find_meta_cols(dena_data$connection.counts)))
set(dena_data$connection.counts, j = i, value = as.ena.co.occurrence(as.double(dena_data$connection.counts[[i]])))
dena_data$model$row.connection.counts = data.table::as.data.table(cbind(dena_data$meta.data, directed.adjacency.vectors))
dena_data$model$row.connection.counts <- rENA::as.ena.matrix(dena_data$model$row.connection.counts, "row.connections")
output = dena_data;
return(output)
}
ona_plot <- function(includeSub = TRUE){
colors <- c("green", "blue", "brown", "purple", "yellow", "deeppink", "Tan", "Cyan", "orange")
p <- ona:::plot.ena.directed.set(set) %>%
units(
points = set$points,
points_color = "white",
point_position_multiplier = point_position_multiplier,
show_mean = FALSE,
show_points = TRUE,
with_ci = FALSE
)
for (i in 1:length(sh_name)) {
tryCatch({
p <- p %>%
units(
points = setA$points[SH == sh_name[i] & Satisfy == "Yes"],
points_color = colors[i],
point_position_multiplier = point_position_multiplier,
show_mean = TRUE,
show_points = FALSE,
with_ci = TRUE
)
}, error = function(e) {
cat("An error occurred:", conditionMessage(e), "\n")
# If an error occurs, set with_ci = FALSE
p <- p %>%
units(
points = setA$points[SH == sh_name[i] & Satisfy == "Yes"],
points_color = colors[i],
point_position_multiplier = point_position_multiplier,
show_mean = TRUE,
show_points = FALSE,
with_ci = FALSE
)
})
}
p <- p %>%
nodes(
node_size_multiplier = 0.01,
node_position_multiplier = node_position_multiplier,
self_connection_color = "blue")
if(includeSub) {
j = 0
k = 1
prev = ""
for (i in 1:length(submission_name)) {
if (submission_name[i] %in% selected_users) {
if (submission_name[i] != prev) {
j <- j+1
prev <- submission_name[i]
k <- 1
}
p <- p %>%
add_annotations(
x = set$points[ENA_DIRECTION == "response"]$SVD1[i],
y = set$points[ENA_DIRECTION == "response"]$SVD2[i],
text = paste0(substring(submission_name[i], 1, 2), "[", k, "]"),
font = list(color = colors_selected[j]),
showarrow = FALSE
)
k <- k+1
}
}
}
p <- p %>%
plotly::layout(showlegend = TRUE, legend = list(x = 100, y = 0.9)) %>%
style(name = "point", traces = c(2)) %>%
style(name = sh_info[1], traces = c(3)) %>%
style(name = sh_info[2], traces = c(4)) %>%
style(name = sh_info[3], traces = c(5)) %>%
style(name = sh_info[4], traces = c(6)) %>%
style(name = sh_info[5], traces = c(7)) %>%
style(name = sh_info[6], traces = c(8)) %>%
style(name = sh_info[7], traces = c(9)) %>%
style(name = sh_info[8], traces = c(10)) %>%
style(name = sh_info[9], traces = c(11))
p <- p %>% layout(xaxis = list(autorange = TRUE),
yaxis = list(autorange = TRUE))
# plotly::export(file = "plots/test.png")
return(p)
}
Reproduce
mapid = "24096504" # change it as appropriate
samplesize <- 10000
init <- jsonlite::fromJSON(paste0("data/", mapid, "_init_map.json"))
reps <- jsonlite::fromJSON(paste0("data/", mapid, "_reps.json"))
indicators <- unique(reps$Indicator)
thresholds_r <- c(0,0,0,0,0)
mul1 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[1])]]))
mul2 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[2])]]))
mul3 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[3])]]))
mul4 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[4])]]))
mul5 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[5])]]))
#set multiplier codes
i1 = 1
i2 = 4
i3 = 1
i4 = 6
i5 = 4
thresholds_r[1] <- mul1[i1]
thresholds_r[2] <- mul2[i2]
thresholds_r[3] <- mul3[i3]
thresholds_r[4] <- mul4[i4]
thresholds_r[5] <- mul5[i5]
reticulate::source_python("py/preABC_generator_hand.py")
source("R/abc_matrix_generator.R")
New CSV file created: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
Data appended to the existing CSV file: D:/Projects/Epistemic Learning/iPlan/iplan-pipeline/data/24096504_c_matrix.csv
#ONA
A_matrix = read_csv(paste0(wd, "/data/", mapid, "_a_matrix.csv"))
B_matrix = read_csv(paste0(wd, "/data/", mapid, "_b_matrix.csv"))
C_matrix = read.csv(paste0(wd, "/data/", mapid, "_c_matrix.csv"))
sh_info = read.csv(paste0(wd, "/data/", "LEM text - Stakeholders.csv"))
A = jsonlite::read_json(paste0(wd, "/data/", mapid, ".json"))
reps = jsonlite::read_json(paste0(wd, "/data/", mapid, "_reps.json"))
sub_result = readRDS(paste0(wd, "/data/", mapid, "a_sub_result_new.rds")) #record satisfy level
submission_name = C_matrix$user_name
submission_order = c()
sub_approval_count = c()
for (i in 1:length(sub_result)){
submission_order = append(submission_order, sub_result[[i]]$userKey)
sub_approval_count = append(sub_approval_count, sub_result[[i]]$approvalCount)
}
sub_approval_count = sub_approval_count/9
sh_name = A_matrix %>%
select(c(Name)) %>%
unique() %>%
pull()
sh_info = sh_info %>%
filter(Name %in% sh_name) %>%
arrange(match(Name, sh_name)) %>%
unite("SHinfo", Name:Direction, remove = TRUE) %>%
pull()
A_matrix_2 <- A_matrix
B_matrix_2 <- B_matrix
C_matrix_2 <- C_matrix
for (i in 1:11) {
A_luc1x = which(names(A_matrix_2)==paste0("luc_", 1, "_", i-1))
A_luc4x = which(names(A_matrix_2)==paste0("luc_", 4, "_", i-1))
B_luc1x = which(names(B_matrix_2)==paste0("luc_", 1, "_", i-1))
B_luc4x = which(names(B_matrix_2)==paste0("luc_", 4, "_", i-1))
C_luc1x = which(names(C_matrix_2)==paste0("luc_", 1, "_", i-1))
C_luc4x = which(names(C_matrix_2)==paste0("luc_", 4, "_", i-1))
A_matrix_2[[A_luc1x]] <- A_matrix_2[[A_luc1x]] + A_matrix_2[[A_luc4x]]
B_matrix_2[[B_luc1x]] <- B_matrix_2[[B_luc1x]] + B_matrix_2[[B_luc4x]]
C_matrix_2[[C_luc1x]] <- C_matrix_2[[C_luc1x]] + C_matrix_2[[C_luc4x]]
}
for (i in 1:11) {
A_lucx1 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 1))
A_lucx4 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 4))
B_lucx1 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 1))
B_lucx4 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 4))
C_lucx1 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 1))
C_lucx4 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 4))
A_matrix_2[[A_lucx1]] <- A_matrix_2[[A_lucx1]] + A_matrix_2[[A_lucx4]]
B_matrix_2[[B_lucx1]] <- B_matrix_2[[B_lucx1]] + B_matrix_2[[B_lucx4]]
C_matrix_2[[C_lucx1]] <- C_matrix_2[[C_lucx1]] + C_matrix_2[[C_lucx4]]
}
for (i in 1:11) {
A_lucxx = which(names(A_matrix_2)==paste0("luc_", i-1, "_", i-1))
B_lucxx = which(names(B_matrix_2)==paste0("luc_", i-1, "_", i-1))
C_lucxx = which(names(C_matrix_2)==paste0("luc_", i-1, "_", i-1))
A_matrix_2[[A_lucxx]] = 0
B_matrix_2[[B_lucxx]] = 0
C_matrix_2[[C_lucxx]] = 0
}
A_matrix_2 <- A_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
B_matrix_2 <- B_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
C_matrix_2 <- C_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
colnames(A_matrix_2)[2] = "SH"
A_matrix_2 <- A_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(A_matrix), .before = "SH")
colnames(B_matrix_2)[2] = "SH"
B_matrix_2 <- B_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(B_matrix), .before = "SH")
C_matrix_2 <- C_matrix_2 %>%
add_column(index = 1:nrow(C_matrix_2), .before = "user_name") %>%
add_column(Name = "NA", .before = "user_name") %>%
add_column(Satisfy = "NA",.before = "user_name") %>%
add_column(N = "NA", .before = "user_name")
df <- C_matrix_2
names(df)[7:106] <- paste0("V",seq(1:100))
df$mapid = mapid
# 2. accum
accumC <- generate.ona.object(
df,
unit.col = df[,1:7],
meta.col = df[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setC <- model(accumC)
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
warning: solve(): system is singular; attempting approx solution
df1 <- A_matrix_2
# df <- B_matrix
# df <- C_matrix
names(df1)[7:106] <- paste0("V",seq(1:100))
df1$mapid = mapid
# 2. accum
accumA <- generate.ona.object(
df1,
unit.col = df1[,1:7],
meta.col = df1[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setA <- model(accumA)
set=model(accumC, rotation.set = setA$rotation)
node_size_multiplier = 0.2
node_position_multiplier = 1.0
edge_size_multiplier = 0.2
point_position_multiplier = 1.0
edge_arrow_saturation_multiplier = 1.0
A = setA$points[ENA_DIRECTION== 'response']
user_names <- unique(C_matrix$user_name)
n <- length(user_names)
colors_selected <- distinctColorPalette(n)
selected_users <- user_names[c(2,3,4,6)] # for 3017613
ona_plot()
Random
mapid = "23917296" # change it as appropriate
samplesize <- 10000
init <- jsonlite::fromJSON(paste0("data/", mapid, "_init_map.json"))
reps <- jsonlite::fromJSON(paste0("data/", mapid, "_reps.json"))
indicators <- unique(reps$Indicator)
thresholds_r <- c(0,0,0,0,0)
mul1 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[1])]]))
mul2 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[2])]]))
mul3 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[3])]]))
mul4 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[4])]]))
mul5 <- sort(unique(init$lucs$multipliers[[which(names(init$lucs$multipliers) == indicators[5])]]))
visited <- c("11111")
i1 = 1
i2 = 1
i3 = 1
i4 = 1
i5 = 1
while (paste0(i1,i2,i3,i4,i5) %in% visited) {
i1 <- sample(1:(length(mul1)-1), 1)
i2 <- sample(1:(length(mul2)-1), 1)
i3 <- sample(1:(length(mul3)-1), 1)
i4 <- sample(1:(length(mul4)-1), 1)
i5 <- sample(1:(length(mul5)-1), 1)
}
visited <- append(visited, paste0(i1,i2,i3,i4,i5))
thresholds_r[1] <- mul1[i1]
thresholds_r[2] <- mul2[i2]
thresholds_r[3] <- mul3[i3]
thresholds_r[4] <- mul4[i4]
thresholds_r[5] <- mul5[i5]
reticulate::source_python("py/preABC_generator_hand.py")
source("R/abc_matrix_generator.R")
#ONA
A_matrix = read_csv(paste0(wd, "/data/", mapid, "_a_matrix.csv"))
B_matrix = read_csv(paste0(wd, "/data/", mapid, "_b_matrix.csv"))
C_matrix = read.csv(paste0(wd, "/data/", mapid, "_c_matrix.csv"))
sh_info = read.csv(paste0(wd, "/data/", "LEM text - Stakeholders.csv"))
A = jsonlite::read_json(paste0(wd, "/data/", mapid, ".json"))
reps = jsonlite::read_json(paste0(wd, "/data/", mapid, "_reps.json"))
sub_result = readRDS(paste0(wd, "/data/", mapid, "a_sub_result_new.rds")) #record satisfy level
submission_name = C_matrix$user_name
submission_order = c()
sub_approval_count = c()
for (i in 1:length(sub_result)){
submission_order = append(submission_order, sub_result[[i]]$userKey)
sub_approval_count = append(sub_approval_count, sub_result[[i]]$approvalCount)
}
sub_approval_count = sub_approval_count/9
sh_name = A_matrix %>%
select(c(Name)) %>%
unique() %>%
pull()
sh_info = sh_info %>%
filter(Name %in% sh_name) %>%
arrange(match(Name, sh_name)) %>%
unite("SHinfo", Name:Direction, remove = TRUE) %>%
pull()
A_matrix_2 <- A_matrix
B_matrix_2 <- B_matrix
C_matrix_2 <- C_matrix
for (i in 1:11) {
A_luc1x = which(names(A_matrix_2)==paste0("luc_", 1, "_", i-1))
A_luc4x = which(names(A_matrix_2)==paste0("luc_", 4, "_", i-1))
B_luc1x = which(names(B_matrix_2)==paste0("luc_", 1, "_", i-1))
B_luc4x = which(names(B_matrix_2)==paste0("luc_", 4, "_", i-1))
C_luc1x = which(names(C_matrix_2)==paste0("luc_", 1, "_", i-1))
C_luc4x = which(names(C_matrix_2)==paste0("luc_", 4, "_", i-1))
A_matrix_2[[A_luc1x]] <- A_matrix_2[[A_luc1x]] + A_matrix_2[[A_luc4x]]
B_matrix_2[[B_luc1x]] <- B_matrix_2[[B_luc1x]] + B_matrix_2[[B_luc4x]]
C_matrix_2[[C_luc1x]] <- C_matrix_2[[C_luc1x]] + C_matrix_2[[C_luc4x]]
}
for (i in 1:11) {
A_lucx1 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 1))
A_lucx4 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 4))
B_lucx1 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 1))
B_lucx4 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 4))
C_lucx1 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 1))
C_lucx4 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 4))
A_matrix_2[[A_lucx1]] <- A_matrix_2[[A_lucx1]] + A_matrix_2[[A_lucx4]]
B_matrix_2[[B_lucx1]] <- B_matrix_2[[B_lucx1]] + B_matrix_2[[B_lucx4]]
C_matrix_2[[C_lucx1]] <- C_matrix_2[[C_lucx1]] + C_matrix_2[[C_lucx4]]
}
for (i in 1:11) {
A_lucxx = which(names(A_matrix_2)==paste0("luc_", i-1, "_", i-1))
B_lucxx = which(names(B_matrix_2)==paste0("luc_", i-1, "_", i-1))
C_lucxx = which(names(C_matrix_2)==paste0("luc_", i-1, "_", i-1))
A_matrix_2[[A_lucxx]] = 0
B_matrix_2[[B_lucxx]] = 0
C_matrix_2[[C_lucxx]] = 0
}
A_matrix_2 <- A_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
B_matrix_2 <- B_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
C_matrix_2 <- C_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
colnames(A_matrix_2)[2] = "SH"
A_matrix_2 <- A_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(A_matrix), .before = "SH")
colnames(B_matrix_2)[2] = "SH"
B_matrix_2 <- B_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(B_matrix), .before = "SH")
C_matrix_2 <- C_matrix_2 %>%
add_column(index = 1:nrow(C_matrix_2), .before = "user_name") %>%
add_column(Name = "NA", .before = "user_name") %>%
add_column(Satisfy = "NA",.before = "user_name") %>%
add_column(N = "NA", .before = "user_name")
df <- C_matrix_2
names(df)[7:106] <- paste0("V",seq(1:100))
df$mapid = mapid
# 2. accum
accumC <- generate.ona.object(
df,
unit.col = df[,1:7],
meta.col = df[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setC <- model(accumC)
df1 <- A_matrix_2
# df <- B_matrix
# df <- C_matrix
names(df1)[7:106] <- paste0("V",seq(1:100))
df1$mapid = mapid
# 2. accum
accumA <- generate.ona.object(
df1,
unit.col = df1[,1:7],
meta.col = df1[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setA <- model(accumA)
set=model(accumC, rotation.set = setA$rotation)
node_size_multiplier = 0.2
node_position_multiplier = 1.0
edge_size_multiplier = 0.2
point_position_multiplier = 1.0
edge_arrow_saturation_multiplier = 1.0
A = setA$points[ENA_DIRECTION== 'response']
user_names <- unique(C_matrix$user_name)
n <- length(user_names)
colors_selected <- distinctColorPalette(n)
selected_users <- user_names[c(2,3,4,6)] # for 3017613
ona_plot()
Brute force
for (i1 in 1:(length(mul1)-3)) {
for (i2 in 1:(length(mul2)-3)) {
for (i3 in 1:(length(mul3)-3)) {
for (i4 in 1:(length(mul4)-3)) {
for (i5 in 1:(length(mul5)-3)) {
thresholds_r[1] <- mul1[i1]
thresholds_r[2] <- mul2[i2]
thresholds_r[3] <- mul3[i3]
thresholds_r[4] <- mul4[i4]
thresholds_r[5] <- mul5[i5]
reticulate::source_python("py/preABC_generator_hand.py")
source("R/abc_matrix_generator.R")
#ONA
A_matrix = read_csv(paste0(wd, "/data/", mapid, "_a_matrix.csv"))
B_matrix = read_csv(paste0(wd, "/data/", mapid, "_b_matrix.csv"))
C_matrix = read.csv(paste0(wd, "/data/", mapid, "_c_matrix.csv"))
sh_info = read.csv(paste0(wd, "/data/", "LEM text - Stakeholders.csv"))
A = jsonlite::read_json(paste0(wd, "/data/", mapid, ".json"))
reps = jsonlite::read_json(paste0(wd, "/data/", mapid, "_reps.json"))
sub_result = readRDS(paste0(wd, "/data/", mapid, "a_sub_result_new.rds")) #record satisfy level
submission_name = C_matrix$user_name
submission_order = c()
sub_approval_count = c()
for (i in 1:length(sub_result)){
submission_order = append(submission_order, sub_result[[i]]$userKey)
sub_approval_count = append(sub_approval_count, sub_result[[i]]$approvalCount)
}
sub_approval_count = sub_approval_count/9
sh_name = A_matrix %>%
select(c(Name)) %>%
unique() %>%
pull()
sh_info = sh_info %>%
filter(Name %in% sh_name) %>%
arrange(match(Name, sh_name)) %>%
unite("SHinfo", Name:Direction, remove = TRUE) %>%
pull()
A_matrix_2 <- A_matrix
B_matrix_2 <- B_matrix
C_matrix_2 <- C_matrix
for (i in 1:11) {
A_luc1x = which(names(A_matrix_2)==paste0("luc_", 1, "_", i-1))
A_luc4x = which(names(A_matrix_2)==paste0("luc_", 4, "_", i-1))
B_luc1x = which(names(B_matrix_2)==paste0("luc_", 1, "_", i-1))
B_luc4x = which(names(B_matrix_2)==paste0("luc_", 4, "_", i-1))
C_luc1x = which(names(C_matrix_2)==paste0("luc_", 1, "_", i-1))
C_luc4x = which(names(C_matrix_2)==paste0("luc_", 4, "_", i-1))
A_matrix_2[[A_luc1x]] <- A_matrix_2[[A_luc1x]] + A_matrix_2[[A_luc4x]]
B_matrix_2[[B_luc1x]] <- B_matrix_2[[B_luc1x]] + B_matrix_2[[B_luc4x]]
C_matrix_2[[C_luc1x]] <- C_matrix_2[[C_luc1x]] + C_matrix_2[[C_luc4x]]
}
for (i in 1:11) {
A_lucx1 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 1))
A_lucx4 = which(names(A_matrix_2)==paste0("luc_", i-1, "_", 4))
B_lucx1 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 1))
B_lucx4 = which(names(B_matrix_2)==paste0("luc_", i-1, "_", 4))
C_lucx1 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 1))
C_lucx4 = which(names(C_matrix_2)==paste0("luc_", i-1, "_", 4))
A_matrix_2[[A_lucx1]] <- A_matrix_2[[A_lucx1]] + A_matrix_2[[A_lucx4]]
B_matrix_2[[B_lucx1]] <- B_matrix_2[[B_lucx1]] + B_matrix_2[[B_lucx4]]
C_matrix_2[[C_lucx1]] <- C_matrix_2[[C_lucx1]] + C_matrix_2[[C_lucx4]]
}
for (i in 1:11) {
A_lucxx = which(names(A_matrix_2)==paste0("luc_", i-1, "_", i-1))
B_lucxx = which(names(B_matrix_2)==paste0("luc_", i-1, "_", i-1))
C_lucxx = which(names(C_matrix_2)==paste0("luc_", i-1, "_", i-1))
A_matrix_2[[A_lucxx]] = 0
B_matrix_2[[B_lucxx]] = 0
C_matrix_2[[C_lucxx]] = 0
}
A_matrix_2 <- A_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
B_matrix_2 <- B_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
C_matrix_2 <- C_matrix_2 %>% select(-c(luc_4_0, luc_4_1, luc_4_2, luc_4_3, luc_4_4,
luc_4_5, luc_4_6, luc_4_7, luc_4_8, luc_4_9, luc_4_10,
luc_0_4, luc_1_4, luc_2_4, luc_3_4, luc_4_4,
luc_5_4, luc_6_4, luc_7_4, luc_8_4, luc_9_4, luc_10_4))
colnames(A_matrix_2)[2] = "SH"
A_matrix_2 <- A_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(A_matrix), .before = "SH")
colnames(B_matrix_2)[2] = "SH"
B_matrix_2 <- B_matrix_2 %>%
select(-c(...1)) %>%
add_column(user_name = "NA", .before = "luc_0_0") %>%
add_column(submission = "NA",.before = "luc_0_0") %>%
add_column(index = 1:nrow(B_matrix), .before = "SH")
C_matrix_2 <- C_matrix_2 %>%
add_column(index = 1:nrow(C_matrix_2), .before = "user_name") %>%
add_column(Name = "NA", .before = "user_name") %>%
add_column(Satisfy = "NA",.before = "user_name") %>%
add_column(N = "NA", .before = "user_name")
df <- C_matrix_2
names(df)[7:106] <- paste0("V",seq(1:100))
df$mapid = mapid
# 2. accum
accumC <- generate.ona.object(
df,
unit.col = df[,1:7],
meta.col = df[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setC <- model(accumC)
df1 <- A_matrix_2
# df <- B_matrix
# df <- C_matrix
names(df1)[7:106] <- paste0("V",seq(1:100))
df1$mapid = mapid
# 2. accum
accumA <- generate.ona.object(
df1,
unit.col = df1[,1:7],
meta.col = df1[,1:7],
codes = as.vector(
c("Commercial",
"Conservation_lu",
# "Conservation",
"Cropland",
"Industrial",
# "Limited Use",
"Pasture",
"Recreation",
"Residential HD",
"Residential LD",
"Timber",
"Wetlands")))
# 3. model
setA <- model(accumA)
set=model(accumC, rotation.set = setA$rotation)
node_size_multiplier = 0.2
node_position_multiplier = 1.0
edge_size_multiplier = 0.2
point_position_multiplier = 1.0
edge_arrow_saturation_multiplier = 1.0
A = setA$points[ENA_DIRECTION== 'response']
user_names <- unique(C_matrix$user_name)
n <- length(user_names)
colors_selected <- distinctColorPalette(n)
selected_users <- user_names[c(2,3,4,6)] # for 3017613
ona_plot()
# plotly::export(file = paste0("plots/", mapid, "/plot_", i1, i2, i3, i4, i5,".png"))
}
}
}
}
}
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCg0KYGBge3J9DQpybShsaXN0ID0gbHMoKSkNCg0KbGlicmFyeSgicnN0dWRpb2FwaSIpDQpzZXR3ZChkaXJuYW1lKGdldEFjdGl2ZURvY3VtZW50Q29udGV4dCgpJHBhdGgpKQ0KDQojIHBsZWFzZSBtYWtlIHN1cmUgeW91ciB3b3JraW5nIGRpcmVjdG9yeSBpcyBzZXQgdG8gdGhpcyBmaWxlIGxvY2F0aW9uDQp3ZCA9IGdldHdkKCkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkockVOQSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShqc29ubGl0ZSkNCmxpYnJhcnkob25hKQ0KbGlicmFyeSh0bWEpDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoZ2dmb3J0aWZ5KQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShzdXBlcmhlYXQpDQpsaWJyYXJ5KHJqc29uKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHJhbmRvbWNvbG9SKQ0KbGlicmFyeShybGlzdCkNCmxpYnJhcnkod2Vic2hvdCkNCmBgYA0KDQpgYGB7cn0NCmdlbmVyYXRlLm9uYS5vYmplY3QgPC0gZnVuY3Rpb24oZGF0YSwgdW5pdC5jb2wsIG1ldGEuY29sLCBjb2Rlcyl7DQogIG91dHB1dCA8LSBsaXN0KCkNCiAgZi51bml0cyA8LSB1bml0LmNvbA0KICBFTkFfVU5JVCA8LSByRU5BOjptZXJnZV9jb2x1bW5zX2MoZi51bml0cywgY29scyA9IGNvbG5hbWVzKGYudW5pdHMpKTsNCiAgIyBFTkFfVU5JVCA8LSAgZi51bml0cw0KICBmLnJhdyA8LSBkYXRhDQogIGYuY29kZXMgPC0gY29kZXMNCiAgZGVuYV9kYXRhID0gZGlyZWN0ZWRFTkE6OjplbmEuc2V0LmRpcmVjdGVkKGYucmF3LCBmLnVuaXRzLCBOQSwgZi5jb2RlcykNCiAgb3V0cHV0Lm1ldGEuZGF0YSA8LSBtZXRhLmNvbA0KICBkZW5hX2RhdGEkbWV0YS5kYXRhIDwtIGRhdGEudGFibGU6OmFzLmRhdGEudGFibGUoY2JpbmQoRU5BX1VOSVQsIG91dHB1dC5tZXRhLmRhdGEpKQ0KICBmb3IoIGkgaW4gY29sbmFtZXMoZGVuYV9kYXRhJG1ldGEuZGF0YSkgKSB7DQogICAgc2V0KGRlbmFfZGF0YSRtZXRhLmRhdGEsIGogPSBpLCB2YWx1ZSA9IHJFTkE6OmFzLmVuYS5tZXRhZGF0YShkZW5hX2RhdGEkbWV0YS5kYXRhW1tpXV0pKQ0KICB9DQogIGNvZGVfbGVuZ3RoIDwtIGxlbmd0aChkZW5hX2RhdGEkcm90YXRpb24kY29kZXMpOw0KICBkZW5hX2RhdGEkcm90YXRpb24kYWRqYWNlbmN5LmtleSA8LSBkYXRhLnRhYmxlOjpkYXRhLnRhYmxlKG1hdHJpeChjKA0KICAgIHJlcCgxOmNvZGVfbGVuZ3RoLCBjb2RlX2xlbmd0aCksDQogICAgcmVwKDE6Y29kZV9sZW5ndGgsIGVhY2ggPSBjb2RlX2xlbmd0aCkpLA0KICAgIGJ5cm93ID0gVFJVRSwgbnJvdyA9IDINCiAgKSkNCiAgZGlyZWN0ZWQuYWRqYWNlbmN5LnZlY3RvcnMgPC0gYXMuZW5hLm1hdHJpeChkYXRhLnRhYmxlOjphcy5kYXRhLnRhYmxlKGRhdGFbLCBncmVwKCJWIiwgY29sbmFtZXMoZGF0YSkpXSksICJlbmEuY29ubmVjdGlvbnMiKQ0KICAjIGFyZW4ndCB0aGVzZSB0d28gdGhlIHNhbWUgdGhpbmcgDQogIGRlbmFfZGF0YSRjb25uZWN0aW9uLmNvdW50cyA8LSBkYXRhLnRhYmxlOjphcy5kYXRhLnRhYmxlKGNiaW5kKGRlbmFfZGF0YSRtZXRhLmRhdGEsIGRpcmVjdGVkLmFkamFjZW5jeS52ZWN0b3JzKSkNCiAgZGVuYV9kYXRhJGNvbm5lY3Rpb24uY291bnRzID0gckVOQTo6YXMuZW5hLm1hdHJpeCh4ID0gZGVuYV9kYXRhJGNvbm5lY3Rpb24uY291bnRzLCAiZW5hLmNvbm5lY3Rpb25zIikNCiAgZm9yIChpIGluIHdoaWNoKCFyRU5BOjpmaW5kX21ldGFfY29scyhkZW5hX2RhdGEkY29ubmVjdGlvbi5jb3VudHMpKSkNCiAgICBzZXQoZGVuYV9kYXRhJGNvbm5lY3Rpb24uY291bnRzLCBqID0gaSwgdmFsdWUgPSBhcy5lbmEuY28ub2NjdXJyZW5jZShhcy5kb3VibGUoZGVuYV9kYXRhJGNvbm5lY3Rpb24uY291bnRzW1tpXV0pKSkNCiAgZGVuYV9kYXRhJG1vZGVsJHJvdy5jb25uZWN0aW9uLmNvdW50cyA9IGRhdGEudGFibGU6OmFzLmRhdGEudGFibGUoY2JpbmQoZGVuYV9kYXRhJG1ldGEuZGF0YSwgZGlyZWN0ZWQuYWRqYWNlbmN5LnZlY3RvcnMpKQ0KICBkZW5hX2RhdGEkbW9kZWwkcm93LmNvbm5lY3Rpb24uY291bnRzIDwtIHJFTkE6OmFzLmVuYS5tYXRyaXgoZGVuYV9kYXRhJG1vZGVsJHJvdy5jb25uZWN0aW9uLmNvdW50cywgInJvdy5jb25uZWN0aW9ucyIpDQogIG91dHB1dCA9IGRlbmFfZGF0YTsNCiAgcmV0dXJuKG91dHB1dCkNCn0NCg0Kb25hX3Bsb3QgPC0gZnVuY3Rpb24oaW5jbHVkZVN1YiA9IFRSVUUpew0KICBjb2xvcnMgPC0gYygiZ3JlZW4iLCAiYmx1ZSIsICJicm93biIsICJwdXJwbGUiLCAieWVsbG93IiwgImRlZXBwaW5rIiwgIlRhbiIsICJDeWFuIiwgIm9yYW5nZSIpDQogIA0KICBwIDwtIG9uYTo6OnBsb3QuZW5hLmRpcmVjdGVkLnNldChzZXQpICU+JQ0KICAgIHVuaXRzKA0KICAgICAgcG9pbnRzID0gc2V0JHBvaW50cywNCiAgICAgIHBvaW50c19jb2xvciA9ICJ3aGl0ZSIsDQogICAgICBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciwNCiAgICAgIHNob3dfbWVhbiA9IEZBTFNFLA0KICAgICAgc2hvd19wb2ludHMgPSBUUlVFLA0KICAgICAgd2l0aF9jaSA9IEZBTFNFDQogICAgKQ0KICANCiAgZm9yIChpIGluIDE6bGVuZ3RoKHNoX25hbWUpKSB7DQogICAgdHJ5Q2F0Y2goew0KICAgICAgcCA8LSBwICU+JQ0KICAgICAgICB1bml0cygNCiAgICAgICAgICBwb2ludHMgPSBzZXRBJHBvaW50c1tTSCA9PSBzaF9uYW1lW2ldICYgU2F0aXNmeSA9PSAiWWVzIl0sDQogICAgICAgICAgcG9pbnRzX2NvbG9yID0gY29sb3JzW2ldLA0KICAgICAgICAgIHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIgPSBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyLA0KICAgICAgICAgIHNob3dfbWVhbiA9IFRSVUUsDQogICAgICAgICAgc2hvd19wb2ludHMgPSBGQUxTRSwNCiAgICAgICAgICB3aXRoX2NpID0gVFJVRQ0KICAgICAgICApDQogICAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7DQogICAgICBjYXQoIkFuIGVycm9yIG9jY3VycmVkOiIsIGNvbmRpdGlvbk1lc3NhZ2UoZSksICJcbiIpDQogICAgICAjIElmIGFuIGVycm9yIG9jY3Vycywgc2V0IHdpdGhfY2kgPSBGQUxTRQ0KICAgICAgcCA8LSBwICU+JQ0KICAgICAgICB1bml0cygNCiAgICAgICAgICBwb2ludHMgPSBzZXRBJHBvaW50c1tTSCA9PSBzaF9uYW1lW2ldICYgU2F0aXNmeSA9PSAiWWVzIl0sDQogICAgICAgICAgcG9pbnRzX2NvbG9yID0gY29sb3JzW2ldLA0KICAgICAgICAgIHBvaW50X3Bvc2l0aW9uX211bHRpcGxpZXIgPSBwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyLA0KICAgICAgICAgIHNob3dfbWVhbiA9IFRSVUUsDQogICAgICAgICAgc2hvd19wb2ludHMgPSBGQUxTRSwNCiAgICAgICAgICB3aXRoX2NpID0gRkFMU0UNCiAgICAgICAgKQ0KICAgIH0pDQogIH0NCiAgDQogIHAgPC0gcCAlPiUNCiAgICBub2RlcygNCiAgICAgIG5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gMC4wMSwNCiAgICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciwNCiAgICAgIHNlbGZfY29ubmVjdGlvbl9jb2xvciA9ICJibHVlIikNCiAgaWYoaW5jbHVkZVN1Yikgew0KICAgIGogPSAwDQogICAgayA9IDENCiAgICBwcmV2ID0gIiINCiAgICBmb3IgKGkgaW4gMTpsZW5ndGgoc3VibWlzc2lvbl9uYW1lKSkgew0KICAgICAgaWYgKHN1Ym1pc3Npb25fbmFtZVtpXSAlaW4lIHNlbGVjdGVkX3VzZXJzKSB7DQogICAgICAgIGlmIChzdWJtaXNzaW9uX25hbWVbaV0gIT0gcHJldikgew0KICAgICAgICAgIGogPC0gaisxDQogICAgICAgICAgcHJldiA8LSBzdWJtaXNzaW9uX25hbWVbaV0NCiAgICAgICAgICBrIDwtIDENCiAgICAgICAgfQ0KICAgICAgICBwIDwtIHAgJT4lDQogICAgICAgICAgYWRkX2Fubm90YXRpb25zKA0KICAgICAgICAgICAgeCA9IHNldCRwb2ludHNbRU5BX0RJUkVDVElPTiA9PSAicmVzcG9uc2UiXSRTVkQxW2ldLA0KICAgICAgICAgICAgeSA9IHNldCRwb2ludHNbRU5BX0RJUkVDVElPTiA9PSAicmVzcG9uc2UiXSRTVkQyW2ldLA0KICAgICAgICAgICAgdGV4dCA9IHBhc3RlMChzdWJzdHJpbmcoc3VibWlzc2lvbl9uYW1lW2ldLCAxLCAyKSwgIlsiLCBrLCAiXSIpLA0KICAgICAgICAgICAgZm9udCA9IGxpc3QoY29sb3IgPSBjb2xvcnNfc2VsZWN0ZWRbal0pLA0KICAgICAgICAgICAgc2hvd2Fycm93ID0gRkFMU0UNCiAgICAgICAgICApDQogICAgICAgIGsgPC0gaysxDQogICAgICB9DQogICAgfQ0KICB9DQogIHAgPC0gcCAlPiUNCiAgICBwbG90bHk6OmxheW91dChzaG93bGVnZW5kID0gVFJVRSwgbGVnZW5kID0gbGlzdCh4ID0gMTAwLCB5ID0gMC45KSkgJT4lIA0KICAgIHN0eWxlKG5hbWUgPSAicG9pbnQiLCB0cmFjZXMgPSBjKDIpKSAlPiUgDQogICAgc3R5bGUobmFtZSA9IHNoX2luZm9bMV0sIHRyYWNlcyA9IGMoMykpICU+JSANCiAgICBzdHlsZShuYW1lID0gc2hfaW5mb1syXSwgdHJhY2VzID0gYyg0KSkgJT4lIA0KICAgIHN0eWxlKG5hbWUgPSBzaF9pbmZvWzNdLCB0cmFjZXMgPSBjKDUpKSAlPiUgDQogICAgc3R5bGUobmFtZSA9IHNoX2luZm9bNF0sIHRyYWNlcyA9IGMoNikpICU+JSANCiAgICBzdHlsZShuYW1lID0gc2hfaW5mb1s1XSwgdHJhY2VzID0gYyg3KSkgJT4lIA0KICAgIHN0eWxlKG5hbWUgPSBzaF9pbmZvWzZdLCB0cmFjZXMgPSBjKDgpKSAlPiUgDQogICAgc3R5bGUobmFtZSA9IHNoX2luZm9bN10sIHRyYWNlcyA9IGMoOSkpICU+JSANCiAgICBzdHlsZShuYW1lID0gc2hfaW5mb1s4XSwgdHJhY2VzID0gYygxMCkpICU+JSANCiAgICBzdHlsZShuYW1lID0gc2hfaW5mb1s5XSwgdHJhY2VzID0gYygxMSkpDQogIHAgPC0gcCAlPiUgbGF5b3V0KHhheGlzID0gbGlzdChhdXRvcmFuZ2UgPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KGF1dG9yYW5nZSA9IFRSVUUpKQ0KICAjIHBsb3RseTo6ZXhwb3J0KGZpbGUgPSAicGxvdHMvdGVzdC5wbmciKQ0KICByZXR1cm4ocCkNCn0NCmBgYA0KDQojIyBSZXByb2R1Y2UNCmBgYHtyfQ0KbWFwaWQgPSAiMjQwOTY1MDQiICMgY2hhbmdlIGl0IGFzIGFwcHJvcHJpYXRlDQpzYW1wbGVzaXplIDwtIDEwMDAwDQoNCmluaXQgPC0ganNvbmxpdGU6OmZyb21KU09OKHBhc3RlMCgiZGF0YS8iLCBtYXBpZCwgIl9pbml0X21hcC5qc29uIikpDQpyZXBzIDwtIGpzb25saXRlOjpmcm9tSlNPTihwYXN0ZTAoImRhdGEvIiwgbWFwaWQsICJfcmVwcy5qc29uIikpDQoNCmluZGljYXRvcnMgPC0gdW5pcXVlKHJlcHMkSW5kaWNhdG9yKQ0KDQp0aHJlc2hvbGRzX3IgPC0gYygwLDAsMCwwLDApDQptdWwxIDwtIHNvcnQodW5pcXVlKGluaXQkbHVjcyRtdWx0aXBsaWVyc1tbd2hpY2gobmFtZXMoaW5pdCRsdWNzJG11bHRpcGxpZXJzKSA9PSBpbmRpY2F0b3JzWzFdKV1dKSkNCm11bDIgPC0gc29ydCh1bmlxdWUoaW5pdCRsdWNzJG11bHRpcGxpZXJzW1t3aGljaChuYW1lcyhpbml0JGx1Y3MkbXVsdGlwbGllcnMpID09IGluZGljYXRvcnNbMl0pXV0pKQ0KbXVsMyA8LSBzb3J0KHVuaXF1ZShpbml0JGx1Y3MkbXVsdGlwbGllcnNbW3doaWNoKG5hbWVzKGluaXQkbHVjcyRtdWx0aXBsaWVycykgPT0gaW5kaWNhdG9yc1szXSldXSkpDQptdWw0IDwtIHNvcnQodW5pcXVlKGluaXQkbHVjcyRtdWx0aXBsaWVyc1tbd2hpY2gobmFtZXMoaW5pdCRsdWNzJG11bHRpcGxpZXJzKSA9PSBpbmRpY2F0b3JzWzRdKV1dKSkNCm11bDUgPC0gc29ydCh1bmlxdWUoaW5pdCRsdWNzJG11bHRpcGxpZXJzW1t3aGljaChuYW1lcyhpbml0JGx1Y3MkbXVsdGlwbGllcnMpID09IGluZGljYXRvcnNbNV0pXV0pKQ0KDQojc2V0IG11bHRpcGxpZXIgY29kZXMNCmkxID0gMQ0KaTIgPSA0DQppMyA9IDENCmk0ID0gNg0KaTUgPSA0DQoNCnRocmVzaG9sZHNfclsxXSA8LSBtdWwxW2kxXQ0KdGhyZXNob2xkc19yWzJdIDwtIG11bDJbaTJdDQp0aHJlc2hvbGRzX3JbM10gPC0gbXVsM1tpM10NCnRocmVzaG9sZHNfcls0XSA8LSBtdWw0W2k0XQ0KdGhyZXNob2xkc19yWzVdIDwtIG11bDVbaTVdDQpgYGANCg0KYGBge3J9DQpyZXRpY3VsYXRlOjpzb3VyY2VfcHl0aG9uKCJweS9wcmVBQkNfZ2VuZXJhdG9yX2hhbmQucHkiKQ0Kc291cmNlKCJSL2FiY19tYXRyaXhfZ2VuZXJhdG9yLlIiKQ0KDQojT05BDQpBX21hdHJpeCA9IHJlYWRfY3N2KHBhc3RlMCh3ZCwgIi9kYXRhLyIsIG1hcGlkLCAiX2FfbWF0cml4LmNzdiIpKQ0KQl9tYXRyaXggPSByZWFkX2NzdihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIl9iX21hdHJpeC5jc3YiKSkNCkNfbWF0cml4ID0gcmVhZC5jc3YocGFzdGUwKHdkLCAiL2RhdGEvIiwgbWFwaWQsICJfY19tYXRyaXguY3N2IikpDQpzaF9pbmZvID0gcmVhZC5jc3YocGFzdGUwKHdkLCAiL2RhdGEvIiwgIkxFTSB0ZXh0IC0gU3Rha2Vob2xkZXJzLmNzdiIpKQ0KQSA9IGpzb25saXRlOjpyZWFkX2pzb24ocGFzdGUwKHdkLCAiL2RhdGEvIiwgbWFwaWQsICIuanNvbiIpKQ0KcmVwcyA9IGpzb25saXRlOjpyZWFkX2pzb24ocGFzdGUwKHdkLCAiL2RhdGEvIiwgbWFwaWQsICJfcmVwcy5qc29uIikpDQpzdWJfcmVzdWx0ID0gcmVhZFJEUyhwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgImFfc3ViX3Jlc3VsdF9uZXcucmRzIikpICNyZWNvcmQgc2F0aXNmeSBsZXZlbA0Kc3VibWlzc2lvbl9uYW1lID0gQ19tYXRyaXgkdXNlcl9uYW1lDQpzdWJtaXNzaW9uX29yZGVyID0gYygpDQpzdWJfYXBwcm92YWxfY291bnQgPSBjKCkNCmZvciAoaSBpbiAxOmxlbmd0aChzdWJfcmVzdWx0KSl7DQogIHN1Ym1pc3Npb25fb3JkZXIgPSBhcHBlbmQoc3VibWlzc2lvbl9vcmRlciwgc3ViX3Jlc3VsdFtbaV1dJHVzZXJLZXkpDQogIHN1Yl9hcHByb3ZhbF9jb3VudCA9IGFwcGVuZChzdWJfYXBwcm92YWxfY291bnQsIHN1Yl9yZXN1bHRbW2ldXSRhcHByb3ZhbENvdW50KQ0KfQ0Kc3ViX2FwcHJvdmFsX2NvdW50ID0gc3ViX2FwcHJvdmFsX2NvdW50LzkNCnNoX25hbWUgPSBBX21hdHJpeCAlPiUNCiAgc2VsZWN0KGMoTmFtZSkpICU+JQ0KICB1bmlxdWUoKSAlPiUNCiAgcHVsbCgpDQpzaF9pbmZvID0gc2hfaW5mbyAlPiUgDQogIGZpbHRlcihOYW1lICVpbiUgc2hfbmFtZSkgJT4lIA0KICBhcnJhbmdlKG1hdGNoKE5hbWUsIHNoX25hbWUpKSAlPiUgDQogIHVuaXRlKCJTSGluZm8iLCBOYW1lOkRpcmVjdGlvbiwgcmVtb3ZlID0gVFJVRSkgJT4lIA0KICBwdWxsKCkNCkFfbWF0cml4XzIgPC0gQV9tYXRyaXgNCkJfbWF0cml4XzIgPC0gQl9tYXRyaXgNCkNfbWF0cml4XzIgPC0gQ19tYXRyaXgNCmZvciAoaSBpbiAxOjExKSB7DQogIEFfbHVjMXggPSB3aGljaChuYW1lcyhBX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgMSwgIl8iLCBpLTEpKQ0KICBBX2x1YzR4ID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDQsICJfIiwgaS0xKSkNCiAgQl9sdWMxeCA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCAxLCAiXyIsIGktMSkpDQogIEJfbHVjNHggPSB3aGljaChuYW1lcyhCX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgNCwgIl8iLCBpLTEpKQ0KICBDX2x1YzF4ID0gd2hpY2gobmFtZXMoQ19tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDEsICJfIiwgaS0xKSkNCiAgQ19sdWM0eCA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCA0LCAiXyIsIGktMSkpDQogIEFfbWF0cml4XzJbW0FfbHVjMXhdXSA8LSBBX21hdHJpeF8yW1tBX2x1YzF4XV0gKyBBX21hdHJpeF8yW1tBX2x1YzR4XV0NCiAgQl9tYXRyaXhfMltbQl9sdWMxeF1dIDwtIEJfbWF0cml4XzJbW0JfbHVjMXhdXSArIEJfbWF0cml4XzJbW0JfbHVjNHhdXQ0KICBDX21hdHJpeF8yW1tDX2x1YzF4XV0gPC0gQ19tYXRyaXhfMltbQ19sdWMxeF1dICsgQ19tYXRyaXhfMltbQ19sdWM0eF1dDQp9DQpmb3IgKGkgaW4gMToxMSkgew0KICBBX2x1Y3gxID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCAxKSkNCiAgQV9sdWN4NCA9IHdoaWNoKG5hbWVzKEFfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgNCkpDQogIEJfbHVjeDEgPSB3aGljaChuYW1lcyhCX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDEpKQ0KICBCX2x1Y3g0ID0gd2hpY2gobmFtZXMoQl9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCA0KSkNCiAgQ19sdWN4MSA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgMSkpDQogIENfbHVjeDQgPSB3aGljaChuYW1lcyhDX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDQpKQ0KICBBX21hdHJpeF8yW1tBX2x1Y3gxXV0gPC0gQV9tYXRyaXhfMltbQV9sdWN4MV1dICsgQV9tYXRyaXhfMltbQV9sdWN4NF1dDQogIEJfbWF0cml4XzJbW0JfbHVjeDFdXSA8LSBCX21hdHJpeF8yW1tCX2x1Y3gxXV0gKyBCX21hdHJpeF8yW1tCX2x1Y3g0XV0NCiAgQ19tYXRyaXhfMltbQ19sdWN4MV1dIDwtIENfbWF0cml4XzJbW0NfbHVjeDFdXSArIENfbWF0cml4XzJbW0NfbHVjeDRdXQ0KfQ0KZm9yIChpIGluIDE6MTEpIHsNCiAgQV9sdWN4eCA9IHdoaWNoKG5hbWVzKEFfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgaS0xKSkNCiAgQl9sdWN4eCA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgaS0xKSkNCiAgQ19sdWN4eCA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgaS0xKSkNCiAgQV9tYXRyaXhfMltbQV9sdWN4eF1dID0gMA0KICBCX21hdHJpeF8yW1tCX2x1Y3h4XV0gPSAwDQogIENfbWF0cml4XzJbW0NfbHVjeHhdXSA9IDANCn0NCg0KQV9tYXRyaXhfMiA8LSBBX21hdHJpeF8yICU+JSBzZWxlY3QoLWMobHVjXzRfMCwgbHVjXzRfMSwgbHVjXzRfMiwgbHVjXzRfMywgbHVjXzRfNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfNF81LCBsdWNfNF82LCBsdWNfNF83LCBsdWNfNF84LCBsdWNfNF85LCBsdWNfNF8xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y18wXzQsIGx1Y18xXzQsIGx1Y18yXzQsIGx1Y18zXzQsIGx1Y180XzQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfNV80LCBsdWNfNl80LCBsdWNfN180LCBsdWNfOF80LCBsdWNfOV80LCBsdWNfMTBfNCkpDQpCX21hdHJpeF8yIDwtIEJfbWF0cml4XzIgJT4lIHNlbGVjdCgtYyhsdWNfNF8wLCBsdWNfNF8xLCBsdWNfNF8yLCBsdWNfNF8zLCBsdWNfNF80LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y180XzUsIGx1Y180XzYsIGx1Y180XzcsIGx1Y180XzgsIGx1Y180XzksIGx1Y180XzEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzBfNCwgbHVjXzFfNCwgbHVjXzJfNCwgbHVjXzNfNCwgbHVjXzRfNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y181XzQsIGx1Y182XzQsIGx1Y183XzQsIGx1Y184XzQsIGx1Y185XzQsIGx1Y18xMF80KSkNCkNfbWF0cml4XzIgPC0gQ19tYXRyaXhfMiAlPiUgc2VsZWN0KC1jKGx1Y180XzAsIGx1Y180XzEsIGx1Y180XzIsIGx1Y180XzMsIGx1Y180XzQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzRfNSwgbHVjXzRfNiwgbHVjXzRfNywgbHVjXzRfOCwgbHVjXzRfOSwgbHVjXzRfMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfMF80LCBsdWNfMV80LCBsdWNfMl80LCBsdWNfM180LCBsdWNfNF80LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzVfNCwgbHVjXzZfNCwgbHVjXzdfNCwgbHVjXzhfNCwgbHVjXzlfNCwgbHVjXzEwXzQpKQ0KY29sbmFtZXMoQV9tYXRyaXhfMilbMl0gPSAiU0giDQpBX21hdHJpeF8yIDwtIEFfbWF0cml4XzIgJT4lDQogIHNlbGVjdCgtYyguLi4xKSkgJT4lIA0KICBhZGRfY29sdW1uKHVzZXJfbmFtZSA9ICJOQSIsIC5iZWZvcmUgPSAibHVjXzBfMCIpICU+JQ0KICBhZGRfY29sdW1uKHN1Ym1pc3Npb24gPSAiTkEiLC5iZWZvcmUgPSAibHVjXzBfMCIpICU+JQ0KICBhZGRfY29sdW1uKGluZGV4ID0gMTpucm93KEFfbWF0cml4KSwgLmJlZm9yZSA9ICJTSCIpDQpjb2xuYW1lcyhCX21hdHJpeF8yKVsyXSA9ICJTSCINCkJfbWF0cml4XzIgPC0gQl9tYXRyaXhfMiAlPiUNCiAgc2VsZWN0KC1jKC4uLjEpKSAlPiUgDQogIGFkZF9jb2x1bW4odXNlcl9uYW1lID0gIk5BIiwgLmJlZm9yZSA9ICJsdWNfMF8wIikgJT4lDQogIGFkZF9jb2x1bW4oc3VibWlzc2lvbiA9ICJOQSIsLmJlZm9yZSA9ICJsdWNfMF8wIikgJT4lDQogIGFkZF9jb2x1bW4oaW5kZXggPSAxOm5yb3coQl9tYXRyaXgpLCAuYmVmb3JlID0gIlNIIikNCkNfbWF0cml4XzIgPC0gQ19tYXRyaXhfMiAlPiUNCiAgYWRkX2NvbHVtbihpbmRleCA9IDE6bnJvdyhDX21hdHJpeF8yKSwgLmJlZm9yZSA9ICJ1c2VyX25hbWUiKSAlPiUNCiAgYWRkX2NvbHVtbihOYW1lID0gIk5BIiwgLmJlZm9yZSA9ICJ1c2VyX25hbWUiKSAlPiUNCiAgYWRkX2NvbHVtbihTYXRpc2Z5ID0gIk5BIiwuYmVmb3JlID0gInVzZXJfbmFtZSIpICU+JQ0KICBhZGRfY29sdW1uKE4gPSAiTkEiLCAuYmVmb3JlID0gInVzZXJfbmFtZSIpDQpkZiA8LSBDX21hdHJpeF8yDQoNCm5hbWVzKGRmKVs3OjEwNl0gPC0gcGFzdGUwKCJWIixzZXEoMToxMDApKQ0KZGYkbWFwaWQgPSBtYXBpZA0KDQojIDIuIGFjY3VtDQphY2N1bUMgPC0gZ2VuZXJhdGUub25hLm9iamVjdCgNCiAgZGYsDQogIHVuaXQuY29sID0gZGZbLDE6N10sDQogIG1ldGEuY29sID0gZGZbLDE6N10sDQogIGNvZGVzID0gYXMudmVjdG9yKA0KICAgIGMoIkNvbW1lcmNpYWwiLA0KICAgICAgIkNvbnNlcnZhdGlvbl9sdSIsDQogICAgICAjICJDb25zZXJ2YXRpb24iLA0KICAgICAgIkNyb3BsYW5kIiwNCiAgICAgICJJbmR1c3RyaWFsIiwNCiAgICAgICMgIkxpbWl0ZWQgVXNlIiwNCiAgICAgICJQYXN0dXJlIiwNCiAgICAgICJSZWNyZWF0aW9uIiwNCiAgICAgICJSZXNpZGVudGlhbCBIRCIsDQogICAgICAiUmVzaWRlbnRpYWwgTEQiLA0KICAgICAgIlRpbWJlciIsDQogICAgICAiV2V0bGFuZHMiKSkpDQoNCiMgMy4gbW9kZWwNCnNldEMgPC0gbW9kZWwoYWNjdW1DKQ0KDQpkZjEgPC0gQV9tYXRyaXhfMg0KIyBkZiA8LSBCX21hdHJpeA0KIyBkZiA8LSBDX21hdHJpeA0KDQpuYW1lcyhkZjEpWzc6MTA2XSA8LSBwYXN0ZTAoIlYiLHNlcSgxOjEwMCkpDQpkZjEkbWFwaWQgPSBtYXBpZA0KDQojIDIuIGFjY3VtDQphY2N1bUEgPC0gZ2VuZXJhdGUub25hLm9iamVjdCgNCiAgZGYxLA0KICB1bml0LmNvbCA9IGRmMVssMTo3XSwNCiAgbWV0YS5jb2wgPSBkZjFbLDE6N10sDQogIGNvZGVzID0gYXMudmVjdG9yKA0KICAgIGMoIkNvbW1lcmNpYWwiLA0KICAgICAgIkNvbnNlcnZhdGlvbl9sdSIsDQogICAgICAjICJDb25zZXJ2YXRpb24iLA0KICAgICAgIkNyb3BsYW5kIiwNCiAgICAgICJJbmR1c3RyaWFsIiwNCiAgICAgICMgIkxpbWl0ZWQgVXNlIiwNCiAgICAgICJQYXN0dXJlIiwNCiAgICAgICJSZWNyZWF0aW9uIiwNCiAgICAgICJSZXNpZGVudGlhbCBIRCIsDQogICAgICAiUmVzaWRlbnRpYWwgTEQiLA0KICAgICAgIlRpbWJlciIsDQogICAgICAiV2V0bGFuZHMiKSkpDQoNCiMgMy4gbW9kZWwNCnNldEEgPC0gbW9kZWwoYWNjdW1BKQ0KDQpzZXQ9bW9kZWwoYWNjdW1DLCByb3RhdGlvbi5zZXQgPSBzZXRBJHJvdGF0aW9uKQ0KDQpub2RlX3NpemVfbXVsdGlwbGllciA9IDAuMg0Kbm9kZV9wb3NpdGlvbl9tdWx0aXBsaWVyID0gMS4wDQplZGdlX3NpemVfbXVsdGlwbGllciA9IDAuMg0KcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IDEuMA0KZWRnZV9hcnJvd19zYXR1cmF0aW9uX211bHRpcGxpZXIgPSAxLjANCg0KQSA9IHNldEEkcG9pbnRzW0VOQV9ESVJFQ1RJT049PSAncmVzcG9uc2UnXQ0KdXNlcl9uYW1lcyA8LSB1bmlxdWUoQ19tYXRyaXgkdXNlcl9uYW1lKQ0KbiA8LSBsZW5ndGgodXNlcl9uYW1lcykNCmNvbG9yc19zZWxlY3RlZCA8LSBkaXN0aW5jdENvbG9yUGFsZXR0ZShuKQ0Kc2VsZWN0ZWRfdXNlcnMgPC0gdXNlcl9uYW1lc1tjKDIsMyw0LDYpXSAjIGZvciAzMDE3NjEzDQpvbmFfcGxvdCgpDQpgYGANCg0KDQoNCiMjIFJhbmRvbQ0KYGBge3J9DQptYXBpZCA9ICIyMzkxNzI5NiIgIyBjaGFuZ2UgaXQgYXMgYXBwcm9wcmlhdGUNCnNhbXBsZXNpemUgPC0gMTAwMDANCg0KaW5pdCA8LSBqc29ubGl0ZTo6ZnJvbUpTT04ocGFzdGUwKCJkYXRhLyIsIG1hcGlkLCAiX2luaXRfbWFwLmpzb24iKSkNCnJlcHMgPC0ganNvbmxpdGU6OmZyb21KU09OKHBhc3RlMCgiZGF0YS8iLCBtYXBpZCwgIl9yZXBzLmpzb24iKSkNCg0KaW5kaWNhdG9ycyA8LSB1bmlxdWUocmVwcyRJbmRpY2F0b3IpDQoNCnRocmVzaG9sZHNfciA8LSBjKDAsMCwwLDAsMCkNCm11bDEgPC0gc29ydCh1bmlxdWUoaW5pdCRsdWNzJG11bHRpcGxpZXJzW1t3aGljaChuYW1lcyhpbml0JGx1Y3MkbXVsdGlwbGllcnMpID09IGluZGljYXRvcnNbMV0pXV0pKQ0KbXVsMiA8LSBzb3J0KHVuaXF1ZShpbml0JGx1Y3MkbXVsdGlwbGllcnNbW3doaWNoKG5hbWVzKGluaXQkbHVjcyRtdWx0aXBsaWVycykgPT0gaW5kaWNhdG9yc1syXSldXSkpDQptdWwzIDwtIHNvcnQodW5pcXVlKGluaXQkbHVjcyRtdWx0aXBsaWVyc1tbd2hpY2gobmFtZXMoaW5pdCRsdWNzJG11bHRpcGxpZXJzKSA9PSBpbmRpY2F0b3JzWzNdKV1dKSkNCm11bDQgPC0gc29ydCh1bmlxdWUoaW5pdCRsdWNzJG11bHRpcGxpZXJzW1t3aGljaChuYW1lcyhpbml0JGx1Y3MkbXVsdGlwbGllcnMpID09IGluZGljYXRvcnNbNF0pXV0pKQ0KbXVsNSA8LSBzb3J0KHVuaXF1ZShpbml0JGx1Y3MkbXVsdGlwbGllcnNbW3doaWNoKG5hbWVzKGluaXQkbHVjcyRtdWx0aXBsaWVycykgPT0gaW5kaWNhdG9yc1s1XSldXSkpDQp2aXNpdGVkIDwtIGMoIjExMTExIikNCmkxID0gMQ0KaTIgPSAxDQppMyA9IDENCmk0ID0gMQ0KaTUgPSAxDQpgYGANCg0KYGBge3J9DQp3aGlsZSAocGFzdGUwKGkxLGkyLGkzLGk0LGk1KSAlaW4lIHZpc2l0ZWQpIHsNCiAgaTEgPC0gc2FtcGxlKDE6KGxlbmd0aChtdWwxKS0xKSwgMSkNCiAgaTIgPC0gc2FtcGxlKDE6KGxlbmd0aChtdWwyKS0xKSwgMSkNCiAgaTMgPC0gc2FtcGxlKDE6KGxlbmd0aChtdWwzKS0xKSwgMSkNCiAgaTQgPC0gc2FtcGxlKDE6KGxlbmd0aChtdWw0KS0xKSwgMSkNCiAgaTUgPC0gc2FtcGxlKDE6KGxlbmd0aChtdWw1KS0xKSwgMSkNCn0NCg0KdmlzaXRlZCA8LSBhcHBlbmQodmlzaXRlZCwgcGFzdGUwKGkxLGkyLGkzLGk0LGk1KSkNCg0KdGhyZXNob2xkc19yWzFdIDwtIG11bDFbaTFdDQp0aHJlc2hvbGRzX3JbMl0gPC0gbXVsMltpMl0NCnRocmVzaG9sZHNfclszXSA8LSBtdWwzW2kzXQ0KdGhyZXNob2xkc19yWzRdIDwtIG11bDRbaTRdDQp0aHJlc2hvbGRzX3JbNV0gPC0gbXVsNVtpNV0NCnJldGljdWxhdGU6OnNvdXJjZV9weXRob24oInB5L3ByZUFCQ19nZW5lcmF0b3JfaGFuZC5weSIpDQpzb3VyY2UoIlIvYWJjX21hdHJpeF9nZW5lcmF0b3IuUiIpDQoNCiNPTkENCkFfbWF0cml4ID0gcmVhZF9jc3YocGFzdGUwKHdkLCAiL2RhdGEvIiwgbWFwaWQsICJfYV9tYXRyaXguY3N2IikpDQpCX21hdHJpeCA9IHJlYWRfY3N2KHBhc3RlMCh3ZCwgIi9kYXRhLyIsIG1hcGlkLCAiX2JfbWF0cml4LmNzdiIpKQ0KQ19tYXRyaXggPSByZWFkLmNzdihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIl9jX21hdHJpeC5jc3YiKSkNCnNoX2luZm8gPSByZWFkLmNzdihwYXN0ZTAod2QsICIvZGF0YS8iLCAiTEVNIHRleHQgLSBTdGFrZWhvbGRlcnMuY3N2IikpDQpBID0ganNvbmxpdGU6OnJlYWRfanNvbihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIi5qc29uIikpDQpyZXBzID0ganNvbmxpdGU6OnJlYWRfanNvbihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIl9yZXBzLmpzb24iKSkNCnN1Yl9yZXN1bHQgPSByZWFkUkRTKHBhc3RlMCh3ZCwgIi9kYXRhLyIsIG1hcGlkLCAiYV9zdWJfcmVzdWx0X25ldy5yZHMiKSkgI3JlY29yZCBzYXRpc2Z5IGxldmVsDQpzdWJtaXNzaW9uX25hbWUgPSBDX21hdHJpeCR1c2VyX25hbWUNCnN1Ym1pc3Npb25fb3JkZXIgPSBjKCkNCnN1Yl9hcHByb3ZhbF9jb3VudCA9IGMoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHN1Yl9yZXN1bHQpKXsNCiAgc3VibWlzc2lvbl9vcmRlciA9IGFwcGVuZChzdWJtaXNzaW9uX29yZGVyLCBzdWJfcmVzdWx0W1tpXV0kdXNlcktleSkNCiAgc3ViX2FwcHJvdmFsX2NvdW50ID0gYXBwZW5kKHN1Yl9hcHByb3ZhbF9jb3VudCwgc3ViX3Jlc3VsdFtbaV1dJGFwcHJvdmFsQ291bnQpDQp9DQpzdWJfYXBwcm92YWxfY291bnQgPSBzdWJfYXBwcm92YWxfY291bnQvOQ0Kc2hfbmFtZSA9IEFfbWF0cml4ICU+JQ0KICBzZWxlY3QoYyhOYW1lKSkgJT4lDQogIHVuaXF1ZSgpICU+JQ0KICBwdWxsKCkNCnNoX2luZm8gPSBzaF9pbmZvICU+JSANCiAgZmlsdGVyKE5hbWUgJWluJSBzaF9uYW1lKSAlPiUgDQogIGFycmFuZ2UobWF0Y2goTmFtZSwgc2hfbmFtZSkpICU+JSANCiAgdW5pdGUoIlNIaW5mbyIsIE5hbWU6RGlyZWN0aW9uLCByZW1vdmUgPSBUUlVFKSAlPiUgDQogIHB1bGwoKQ0KQV9tYXRyaXhfMiA8LSBBX21hdHJpeA0KQl9tYXRyaXhfMiA8LSBCX21hdHJpeA0KQ19tYXRyaXhfMiA8LSBDX21hdHJpeA0KZm9yIChpIGluIDE6MTEpIHsNCiAgQV9sdWMxeCA9IHdoaWNoKG5hbWVzKEFfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCAxLCAiXyIsIGktMSkpDQogIEFfbHVjNHggPSB3aGljaChuYW1lcyhBX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgNCwgIl8iLCBpLTEpKQ0KICBCX2x1YzF4ID0gd2hpY2gobmFtZXMoQl9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDEsICJfIiwgaS0xKSkNCiAgQl9sdWM0eCA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCA0LCAiXyIsIGktMSkpDQogIENfbHVjMXggPSB3aGljaChuYW1lcyhDX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgMSwgIl8iLCBpLTEpKQ0KICBDX2x1YzR4ID0gd2hpY2gobmFtZXMoQ19tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDQsICJfIiwgaS0xKSkNCiAgQV9tYXRyaXhfMltbQV9sdWMxeF1dIDwtIEFfbWF0cml4XzJbW0FfbHVjMXhdXSArIEFfbWF0cml4XzJbW0FfbHVjNHhdXQ0KICBCX21hdHJpeF8yW1tCX2x1YzF4XV0gPC0gQl9tYXRyaXhfMltbQl9sdWMxeF1dICsgQl9tYXRyaXhfMltbQl9sdWM0eF1dDQogIENfbWF0cml4XzJbW0NfbHVjMXhdXSA8LSBDX21hdHJpeF8yW1tDX2x1YzF4XV0gKyBDX21hdHJpeF8yW1tDX2x1YzR4XV0NCn0NCmZvciAoaSBpbiAxOjExKSB7DQogIEFfbHVjeDEgPSB3aGljaChuYW1lcyhBX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDEpKQ0KICBBX2x1Y3g0ID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCA0KSkNCiAgQl9sdWN4MSA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgMSkpDQogIEJfbHVjeDQgPSB3aGljaChuYW1lcyhCX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDQpKQ0KICBDX2x1Y3gxID0gd2hpY2gobmFtZXMoQ19tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCAxKSkNCiAgQ19sdWN4NCA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgNCkpDQogIEFfbWF0cml4XzJbW0FfbHVjeDFdXSA8LSBBX21hdHJpeF8yW1tBX2x1Y3gxXV0gKyBBX21hdHJpeF8yW1tBX2x1Y3g0XV0NCiAgQl9tYXRyaXhfMltbQl9sdWN4MV1dIDwtIEJfbWF0cml4XzJbW0JfbHVjeDFdXSArIEJfbWF0cml4XzJbW0JfbHVjeDRdXQ0KICBDX21hdHJpeF8yW1tDX2x1Y3gxXV0gPC0gQ19tYXRyaXhfMltbQ19sdWN4MV1dICsgQ19tYXRyaXhfMltbQ19sdWN4NF1dDQp9DQpmb3IgKGkgaW4gMToxMSkgew0KICBBX2x1Y3h4ID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCBpLTEpKQ0KICBCX2x1Y3h4ID0gd2hpY2gobmFtZXMoQl9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCBpLTEpKQ0KICBDX2x1Y3h4ID0gd2hpY2gobmFtZXMoQ19tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCBpLTEpKQ0KICBBX21hdHJpeF8yW1tBX2x1Y3h4XV0gPSAwDQogIEJfbWF0cml4XzJbW0JfbHVjeHhdXSA9IDANCiAgQ19tYXRyaXhfMltbQ19sdWN4eF1dID0gMA0KfQ0KDQpBX21hdHJpeF8yIDwtIEFfbWF0cml4XzIgJT4lIHNlbGVjdCgtYyhsdWNfNF8wLCBsdWNfNF8xLCBsdWNfNF8yLCBsdWNfNF8zLCBsdWNfNF80LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y180XzUsIGx1Y180XzYsIGx1Y180XzcsIGx1Y180XzgsIGx1Y180XzksIGx1Y180XzEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzBfNCwgbHVjXzFfNCwgbHVjXzJfNCwgbHVjXzNfNCwgbHVjXzRfNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y181XzQsIGx1Y182XzQsIGx1Y183XzQsIGx1Y184XzQsIGx1Y185XzQsIGx1Y18xMF80KSkNCkJfbWF0cml4XzIgPC0gQl9tYXRyaXhfMiAlPiUgc2VsZWN0KC1jKGx1Y180XzAsIGx1Y180XzEsIGx1Y180XzIsIGx1Y180XzMsIGx1Y180XzQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzRfNSwgbHVjXzRfNiwgbHVjXzRfNywgbHVjXzRfOCwgbHVjXzRfOSwgbHVjXzRfMTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfMF80LCBsdWNfMV80LCBsdWNfMl80LCBsdWNfM180LCBsdWNfNF80LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzVfNCwgbHVjXzZfNCwgbHVjXzdfNCwgbHVjXzhfNCwgbHVjXzlfNCwgbHVjXzEwXzQpKQ0KQ19tYXRyaXhfMiA8LSBDX21hdHJpeF8yICU+JSBzZWxlY3QoLWMobHVjXzRfMCwgbHVjXzRfMSwgbHVjXzRfMiwgbHVjXzRfMywgbHVjXzRfNCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfNF81LCBsdWNfNF82LCBsdWNfNF83LCBsdWNfNF84LCBsdWNfNF85LCBsdWNfNF8xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y18wXzQsIGx1Y18xXzQsIGx1Y18yXzQsIGx1Y18zXzQsIGx1Y180XzQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsdWNfNV80LCBsdWNfNl80LCBsdWNfN180LCBsdWNfOF80LCBsdWNfOV80LCBsdWNfMTBfNCkpDQpjb2xuYW1lcyhBX21hdHJpeF8yKVsyXSA9ICJTSCINCkFfbWF0cml4XzIgPC0gQV9tYXRyaXhfMiAlPiUNCiAgc2VsZWN0KC1jKC4uLjEpKSAlPiUgDQogIGFkZF9jb2x1bW4odXNlcl9uYW1lID0gIk5BIiwgLmJlZm9yZSA9ICJsdWNfMF8wIikgJT4lDQogIGFkZF9jb2x1bW4oc3VibWlzc2lvbiA9ICJOQSIsLmJlZm9yZSA9ICJsdWNfMF8wIikgJT4lDQogIGFkZF9jb2x1bW4oaW5kZXggPSAxOm5yb3coQV9tYXRyaXgpLCAuYmVmb3JlID0gIlNIIikNCmNvbG5hbWVzKEJfbWF0cml4XzIpWzJdID0gIlNIIg0KQl9tYXRyaXhfMiA8LSBCX21hdHJpeF8yICU+JQ0KICBzZWxlY3QoLWMoLi4uMSkpICU+JSANCiAgYWRkX2NvbHVtbih1c2VyX25hbWUgPSAiTkEiLCAuYmVmb3JlID0gImx1Y18wXzAiKSAlPiUNCiAgYWRkX2NvbHVtbihzdWJtaXNzaW9uID0gIk5BIiwuYmVmb3JlID0gImx1Y18wXzAiKSAlPiUNCiAgYWRkX2NvbHVtbihpbmRleCA9IDE6bnJvdyhCX21hdHJpeCksIC5iZWZvcmUgPSAiU0giKQ0KQ19tYXRyaXhfMiA8LSBDX21hdHJpeF8yICU+JQ0KICBhZGRfY29sdW1uKGluZGV4ID0gMTpucm93KENfbWF0cml4XzIpLCAuYmVmb3JlID0gInVzZXJfbmFtZSIpICU+JQ0KICBhZGRfY29sdW1uKE5hbWUgPSAiTkEiLCAuYmVmb3JlID0gInVzZXJfbmFtZSIpICU+JQ0KICBhZGRfY29sdW1uKFNhdGlzZnkgPSAiTkEiLC5iZWZvcmUgPSAidXNlcl9uYW1lIikgJT4lDQogIGFkZF9jb2x1bW4oTiA9ICJOQSIsIC5iZWZvcmUgPSAidXNlcl9uYW1lIikNCmRmIDwtIENfbWF0cml4XzINCg0KbmFtZXMoZGYpWzc6MTA2XSA8LSBwYXN0ZTAoIlYiLHNlcSgxOjEwMCkpDQpkZiRtYXBpZCA9IG1hcGlkDQoNCiMgMi4gYWNjdW0NCmFjY3VtQyA8LSBnZW5lcmF0ZS5vbmEub2JqZWN0KA0KICBkZiwNCiAgdW5pdC5jb2wgPSBkZlssMTo3XSwNCiAgbWV0YS5jb2wgPSBkZlssMTo3XSwNCiAgY29kZXMgPSBhcy52ZWN0b3IoDQogICAgYygiQ29tbWVyY2lhbCIsDQogICAgICAiQ29uc2VydmF0aW9uX2x1IiwNCiAgICAgICMgIkNvbnNlcnZhdGlvbiIsDQogICAgICAiQ3JvcGxhbmQiLA0KICAgICAgIkluZHVzdHJpYWwiLA0KICAgICAgIyAiTGltaXRlZCBVc2UiLA0KICAgICAgIlBhc3R1cmUiLA0KICAgICAgIlJlY3JlYXRpb24iLA0KICAgICAgIlJlc2lkZW50aWFsIEhEIiwNCiAgICAgICJSZXNpZGVudGlhbCBMRCIsDQogICAgICAiVGltYmVyIiwNCiAgICAgICJXZXRsYW5kcyIpKSkNCg0KIyAzLiBtb2RlbA0Kc2V0QyA8LSBtb2RlbChhY2N1bUMpDQoNCmRmMSA8LSBBX21hdHJpeF8yDQojIGRmIDwtIEJfbWF0cml4DQojIGRmIDwtIENfbWF0cml4DQoNCm5hbWVzKGRmMSlbNzoxMDZdIDwtIHBhc3RlMCgiViIsc2VxKDE6MTAwKSkNCmRmMSRtYXBpZCA9IG1hcGlkDQoNCiMgMi4gYWNjdW0NCmFjY3VtQSA8LSBnZW5lcmF0ZS5vbmEub2JqZWN0KA0KICBkZjEsDQogIHVuaXQuY29sID0gZGYxWywxOjddLA0KICBtZXRhLmNvbCA9IGRmMVssMTo3XSwNCiAgY29kZXMgPSBhcy52ZWN0b3IoDQogICAgYygiQ29tbWVyY2lhbCIsDQogICAgICAiQ29uc2VydmF0aW9uX2x1IiwNCiAgICAgICMgIkNvbnNlcnZhdGlvbiIsDQogICAgICAiQ3JvcGxhbmQiLA0KICAgICAgIkluZHVzdHJpYWwiLA0KICAgICAgIyAiTGltaXRlZCBVc2UiLA0KICAgICAgIlBhc3R1cmUiLA0KICAgICAgIlJlY3JlYXRpb24iLA0KICAgICAgIlJlc2lkZW50aWFsIEhEIiwNCiAgICAgICJSZXNpZGVudGlhbCBMRCIsDQogICAgICAiVGltYmVyIiwNCiAgICAgICJXZXRsYW5kcyIpKSkNCg0KIyAzLiBtb2RlbA0Kc2V0QSA8LSBtb2RlbChhY2N1bUEpDQoNCnNldD1tb2RlbChhY2N1bUMsIHJvdGF0aW9uLnNldCA9IHNldEEkcm90YXRpb24pDQoNCm5vZGVfc2l6ZV9tdWx0aXBsaWVyID0gMC4yDQpub2RlX3Bvc2l0aW9uX211bHRpcGxpZXIgPSAxLjANCmVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gMC4yDQpwb2ludF9wb3NpdGlvbl9tdWx0aXBsaWVyID0gMS4wDQplZGdlX2Fycm93X3NhdHVyYXRpb25fbXVsdGlwbGllciA9IDEuMA0KDQpBID0gc2V0QSRwb2ludHNbRU5BX0RJUkVDVElPTj09ICdyZXNwb25zZSddDQp1c2VyX25hbWVzIDwtIHVuaXF1ZShDX21hdHJpeCR1c2VyX25hbWUpDQpuIDwtIGxlbmd0aCh1c2VyX25hbWVzKQ0KY29sb3JzX3NlbGVjdGVkIDwtIGRpc3RpbmN0Q29sb3JQYWxldHRlKG4pDQpzZWxlY3RlZF91c2VycyA8LSB1c2VyX25hbWVzW2MoMiwzLDQsNildICMgZm9yIDMwMTc2MTMNCm9uYV9wbG90KCkNCmBgYA0KDQojIyBCcnV0ZSBmb3JjZQ0KYGBge3J9DQpmb3IgKGkxIGluIDE6KGxlbmd0aChtdWwxKS0zKSkgew0KICBmb3IgKGkyIGluIDE6KGxlbmd0aChtdWwyKS0zKSkgew0KICAgIGZvciAoaTMgaW4gMToobGVuZ3RoKG11bDMpLTMpKSB7DQogICAgICBmb3IgKGk0IGluIDE6KGxlbmd0aChtdWw0KS0zKSkgew0KICAgICAgICBmb3IgKGk1IGluIDE6KGxlbmd0aChtdWw1KS0zKSkgew0KICAgICAgICAgIHRocmVzaG9sZHNfclsxXSA8LSBtdWwxW2kxXQ0KICAgICAgICAgIHRocmVzaG9sZHNfclsyXSA8LSBtdWwyW2kyXQ0KICAgICAgICAgIHRocmVzaG9sZHNfclszXSA8LSBtdWwzW2kzXQ0KICAgICAgICAgIHRocmVzaG9sZHNfcls0XSA8LSBtdWw0W2k0XQ0KICAgICAgICAgIHRocmVzaG9sZHNfcls1XSA8LSBtdWw1W2k1XQ0KICAgICAgICAgIHJldGljdWxhdGU6OnNvdXJjZV9weXRob24oInB5L3ByZUFCQ19nZW5lcmF0b3JfaGFuZC5weSIpDQogICAgICAgICAgc291cmNlKCJSL2FiY19tYXRyaXhfZ2VuZXJhdG9yLlIiKQ0KICAgICAgICAgIA0KICAgICAgICAgICNPTkENCiAgICAgICAgICBBX21hdHJpeCA9IHJlYWRfY3N2KHBhc3RlMCh3ZCwgIi9kYXRhLyIsIG1hcGlkLCAiX2FfbWF0cml4LmNzdiIpKQ0KICAgICAgICAgIEJfbWF0cml4ID0gcmVhZF9jc3YocGFzdGUwKHdkLCAiL2RhdGEvIiwgbWFwaWQsICJfYl9tYXRyaXguY3N2IikpDQogICAgICAgICAgQ19tYXRyaXggPSByZWFkLmNzdihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIl9jX21hdHJpeC5jc3YiKSkNCiAgICAgICAgICBzaF9pbmZvID0gcmVhZC5jc3YocGFzdGUwKHdkLCAiL2RhdGEvIiwgIkxFTSB0ZXh0IC0gU3Rha2Vob2xkZXJzLmNzdiIpKQ0KICAgICAgICAgIEEgPSBqc29ubGl0ZTo6cmVhZF9qc29uKHBhc3RlMCh3ZCwgIi9kYXRhLyIsIG1hcGlkLCAiLmpzb24iKSkNCiAgICAgICAgICByZXBzID0ganNvbmxpdGU6OnJlYWRfanNvbihwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgIl9yZXBzLmpzb24iKSkNCiAgICAgICAgICBzdWJfcmVzdWx0ID0gcmVhZFJEUyhwYXN0ZTAod2QsICIvZGF0YS8iLCBtYXBpZCwgImFfc3ViX3Jlc3VsdF9uZXcucmRzIikpICNyZWNvcmQgc2F0aXNmeSBsZXZlbA0KICAgICAgICAgIHN1Ym1pc3Npb25fbmFtZSA9IENfbWF0cml4JHVzZXJfbmFtZQ0KICAgICAgICAgIHN1Ym1pc3Npb25fb3JkZXIgPSBjKCkNCiAgICAgICAgICBzdWJfYXBwcm92YWxfY291bnQgPSBjKCkNCiAgICAgICAgICBmb3IgKGkgaW4gMTpsZW5ndGgoc3ViX3Jlc3VsdCkpew0KICAgICAgICAgICAgc3VibWlzc2lvbl9vcmRlciA9IGFwcGVuZChzdWJtaXNzaW9uX29yZGVyLCBzdWJfcmVzdWx0W1tpXV0kdXNlcktleSkNCiAgICAgICAgICAgIHN1Yl9hcHByb3ZhbF9jb3VudCA9IGFwcGVuZChzdWJfYXBwcm92YWxfY291bnQsIHN1Yl9yZXN1bHRbW2ldXSRhcHByb3ZhbENvdW50KQ0KICAgICAgICAgIH0NCiAgICAgICAgICBzdWJfYXBwcm92YWxfY291bnQgPSBzdWJfYXBwcm92YWxfY291bnQvOQ0KICAgICAgICAgIHNoX25hbWUgPSBBX21hdHJpeCAlPiUNCiAgICAgICAgICAgIHNlbGVjdChjKE5hbWUpKSAlPiUNCiAgICAgICAgICAgIHVuaXF1ZSgpICU+JQ0KICAgICAgICAgICAgcHVsbCgpDQogICAgICAgICAgc2hfaW5mbyA9IHNoX2luZm8gJT4lIA0KICAgICAgICAgICAgZmlsdGVyKE5hbWUgJWluJSBzaF9uYW1lKSAlPiUgDQogICAgICAgICAgICBhcnJhbmdlKG1hdGNoKE5hbWUsIHNoX25hbWUpKSAlPiUgDQogICAgICAgICAgICB1bml0ZSgiU0hpbmZvIiwgTmFtZTpEaXJlY3Rpb24sIHJlbW92ZSA9IFRSVUUpICU+JSANCiAgICAgICAgICAgIHB1bGwoKQ0KICAgICAgICAgIEFfbWF0cml4XzIgPC0gQV9tYXRyaXgNCiAgICAgICAgICBCX21hdHJpeF8yIDwtIEJfbWF0cml4DQogICAgICAgICAgQ19tYXRyaXhfMiA8LSBDX21hdHJpeA0KICAgICAgICAgIGZvciAoaSBpbiAxOjExKSB7DQogICAgICAgICAgICBBX2x1YzF4ID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDEsICJfIiwgaS0xKSkNCiAgICAgICAgICAgIEFfbHVjNHggPSB3aGljaChuYW1lcyhBX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgNCwgIl8iLCBpLTEpKQ0KICAgICAgICAgICAgQl9sdWMxeCA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCAxLCAiXyIsIGktMSkpDQogICAgICAgICAgICBCX2x1YzR4ID0gd2hpY2gobmFtZXMoQl9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIDQsICJfIiwgaS0xKSkNCiAgICAgICAgICAgIENfbHVjMXggPSB3aGljaChuYW1lcyhDX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgMSwgIl8iLCBpLTEpKQ0KICAgICAgICAgICAgQ19sdWM0eCA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCA0LCAiXyIsIGktMSkpDQogICAgICAgICAgICBBX21hdHJpeF8yW1tBX2x1YzF4XV0gPC0gQV9tYXRyaXhfMltbQV9sdWMxeF1dICsgQV9tYXRyaXhfMltbQV9sdWM0eF1dDQogICAgICAgICAgICBCX21hdHJpeF8yW1tCX2x1YzF4XV0gPC0gQl9tYXRyaXhfMltbQl9sdWMxeF1dICsgQl9tYXRyaXhfMltbQl9sdWM0eF1dDQogICAgICAgICAgICBDX21hdHJpeF8yW1tDX2x1YzF4XV0gPC0gQ19tYXRyaXhfMltbQ19sdWMxeF1dICsgQ19tYXRyaXhfMltbQ19sdWM0eF1dDQogICAgICAgICAgfQ0KICAgICAgICAgIGZvciAoaSBpbiAxOjExKSB7DQogICAgICAgICAgICBBX2x1Y3gxID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCAxKSkNCiAgICAgICAgICAgIEFfbHVjeDQgPSB3aGljaChuYW1lcyhBX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDQpKQ0KICAgICAgICAgICAgQl9sdWN4MSA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgMSkpDQogICAgICAgICAgICBCX2x1Y3g0ID0gd2hpY2gobmFtZXMoQl9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCA0KSkNCiAgICAgICAgICAgIENfbHVjeDEgPSB3aGljaChuYW1lcyhDX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIDEpKQ0KICAgICAgICAgICAgQ19sdWN4NCA9IHdoaWNoKG5hbWVzKENfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgNCkpDQogICAgICAgICAgICBBX21hdHJpeF8yW1tBX2x1Y3gxXV0gPC0gQV9tYXRyaXhfMltbQV9sdWN4MV1dICsgQV9tYXRyaXhfMltbQV9sdWN4NF1dDQogICAgICAgICAgICBCX21hdHJpeF8yW1tCX2x1Y3gxXV0gPC0gQl9tYXRyaXhfMltbQl9sdWN4MV1dICsgQl9tYXRyaXhfMltbQl9sdWN4NF1dDQogICAgICAgICAgICBDX21hdHJpeF8yW1tDX2x1Y3gxXV0gPC0gQ19tYXRyaXhfMltbQ19sdWN4MV1dICsgQ19tYXRyaXhfMltbQ19sdWN4NF1dDQogICAgICAgICAgfQ0KICAgICAgICAgIGZvciAoaSBpbiAxOjExKSB7DQogICAgICAgICAgICBBX2x1Y3h4ID0gd2hpY2gobmFtZXMoQV9tYXRyaXhfMik9PXBhc3RlMCgibHVjXyIsIGktMSwgIl8iLCBpLTEpKQ0KICAgICAgICAgICAgQl9sdWN4eCA9IHdoaWNoKG5hbWVzKEJfbWF0cml4XzIpPT1wYXN0ZTAoImx1Y18iLCBpLTEsICJfIiwgaS0xKSkNCiAgICAgICAgICAgIENfbHVjeHggPSB3aGljaChuYW1lcyhDX21hdHJpeF8yKT09cGFzdGUwKCJsdWNfIiwgaS0xLCAiXyIsIGktMSkpDQogICAgICAgICAgICBBX21hdHJpeF8yW1tBX2x1Y3h4XV0gPSAwDQogICAgICAgICAgICBCX21hdHJpeF8yW1tCX2x1Y3h4XV0gPSAwDQogICAgICAgICAgICBDX21hdHJpeF8yW1tDX2x1Y3h4XV0gPSAwDQogICAgICAgICAgfQ0KICAgICAgICAgIA0KICAgICAgICAgIEFfbWF0cml4XzIgPC0gQV9tYXRyaXhfMiAlPiUgc2VsZWN0KC1jKGx1Y180XzAsIGx1Y180XzEsIGx1Y180XzIsIGx1Y180XzMsIGx1Y180XzQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y180XzUsIGx1Y180XzYsIGx1Y180XzcsIGx1Y180XzgsIGx1Y180XzksIGx1Y180XzEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y18wXzQsIGx1Y18xXzQsIGx1Y18yXzQsIGx1Y18zXzQsIGx1Y180XzQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzVfNCwgbHVjXzZfNCwgbHVjXzdfNCwgbHVjXzhfNCwgbHVjXzlfNCwgbHVjXzEwXzQpKQ0KICAgICAgICAgIEJfbWF0cml4XzIgPC0gQl9tYXRyaXhfMiAlPiUgc2VsZWN0KC1jKGx1Y180XzAsIGx1Y180XzEsIGx1Y180XzIsIGx1Y180XzMsIGx1Y180XzQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y180XzUsIGx1Y180XzYsIGx1Y180XzcsIGx1Y180XzgsIGx1Y180XzksIGx1Y180XzEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y18wXzQsIGx1Y18xXzQsIGx1Y18yXzQsIGx1Y18zXzQsIGx1Y180XzQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzVfNCwgbHVjXzZfNCwgbHVjXzdfNCwgbHVjXzhfNCwgbHVjXzlfNCwgbHVjXzEwXzQpKQ0KICAgICAgICAgIENfbWF0cml4XzIgPC0gQ19tYXRyaXhfMiAlPiUgc2VsZWN0KC1jKGx1Y180XzAsIGx1Y180XzEsIGx1Y180XzIsIGx1Y180XzMsIGx1Y180XzQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y180XzUsIGx1Y180XzYsIGx1Y180XzcsIGx1Y180XzgsIGx1Y180XzksIGx1Y180XzEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1Y18wXzQsIGx1Y18xXzQsIGx1Y18yXzQsIGx1Y18zXzQsIGx1Y180XzQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVjXzVfNCwgbHVjXzZfNCwgbHVjXzdfNCwgbHVjXzhfNCwgbHVjXzlfNCwgbHVjXzEwXzQpKQ0KICAgICAgICAgIGNvbG5hbWVzKEFfbWF0cml4XzIpWzJdID0gIlNIIg0KICAgICAgICAgIEFfbWF0cml4XzIgPC0gQV9tYXRyaXhfMiAlPiUNCiAgICAgICAgICAgIHNlbGVjdCgtYyguLi4xKSkgJT4lIA0KICAgICAgICAgICAgYWRkX2NvbHVtbih1c2VyX25hbWUgPSAiTkEiLCAuYmVmb3JlID0gImx1Y18wXzAiKSAlPiUNCiAgICAgICAgICAgIGFkZF9jb2x1bW4oc3VibWlzc2lvbiA9ICJOQSIsLmJlZm9yZSA9ICJsdWNfMF8wIikgJT4lDQogICAgICAgICAgICBhZGRfY29sdW1uKGluZGV4ID0gMTpucm93KEFfbWF0cml4KSwgLmJlZm9yZSA9ICJTSCIpDQogICAgICAgICAgY29sbmFtZXMoQl9tYXRyaXhfMilbMl0gPSAiU0giDQogICAgICAgICAgQl9tYXRyaXhfMiA8LSBCX21hdHJpeF8yICU+JQ0KICAgICAgICAgICAgc2VsZWN0KC1jKC4uLjEpKSAlPiUgDQogICAgICAgICAgICBhZGRfY29sdW1uKHVzZXJfbmFtZSA9ICJOQSIsIC5iZWZvcmUgPSAibHVjXzBfMCIpICU+JQ0KICAgICAgICAgICAgYWRkX2NvbHVtbihzdWJtaXNzaW9uID0gIk5BIiwuYmVmb3JlID0gImx1Y18wXzAiKSAlPiUNCiAgICAgICAgICAgIGFkZF9jb2x1bW4oaW5kZXggPSAxOm5yb3coQl9tYXRyaXgpLCAuYmVmb3JlID0gIlNIIikNCiAgICAgICAgICBDX21hdHJpeF8yIDwtIENfbWF0cml4XzIgJT4lDQogICAgICAgICAgICBhZGRfY29sdW1uKGluZGV4ID0gMTpucm93KENfbWF0cml4XzIpLCAuYmVmb3JlID0gInVzZXJfbmFtZSIpICU+JQ0KICAgICAgICAgICAgYWRkX2NvbHVtbihOYW1lID0gIk5BIiwgLmJlZm9yZSA9ICJ1c2VyX25hbWUiKSAlPiUNCiAgICAgICAgICAgIGFkZF9jb2x1bW4oU2F0aXNmeSA9ICJOQSIsLmJlZm9yZSA9ICJ1c2VyX25hbWUiKSAlPiUNCiAgICAgICAgICAgIGFkZF9jb2x1bW4oTiA9ICJOQSIsIC5iZWZvcmUgPSAidXNlcl9uYW1lIikNCiAgICAgICAgICBkZiA8LSBDX21hdHJpeF8yDQogICAgICAgICAgDQogICAgICAgICAgbmFtZXMoZGYpWzc6MTA2XSA8LSBwYXN0ZTAoIlYiLHNlcSgxOjEwMCkpDQogICAgICAgICAgZGYkbWFwaWQgPSBtYXBpZA0KICAgICAgICAgIA0KICAgICAgICAgICMgMi4gYWNjdW0NCiAgICAgICAgICBhY2N1bUMgPC0gZ2VuZXJhdGUub25hLm9iamVjdCgNCiAgICAgICAgICAgIGRmLA0KICAgICAgICAgICAgdW5pdC5jb2wgPSBkZlssMTo3XSwNCiAgICAgICAgICAgIG1ldGEuY29sID0gZGZbLDE6N10sDQogICAgICAgICAgICBjb2RlcyA9IGFzLnZlY3RvcigNCiAgICAgICAgICAgICAgYygiQ29tbWVyY2lhbCIsDQogICAgICAgICAgICAgICAgIkNvbnNlcnZhdGlvbl9sdSIsDQogICAgICAgICAgICAgICAgIyAiQ29uc2VydmF0aW9uIiwNCiAgICAgICAgICAgICAgICAiQ3JvcGxhbmQiLA0KICAgICAgICAgICAgICAgICJJbmR1c3RyaWFsIiwNCiAgICAgICAgICAgICAgICAjICJMaW1pdGVkIFVzZSIsDQogICAgICAgICAgICAgICAgIlBhc3R1cmUiLA0KICAgICAgICAgICAgICAgICJSZWNyZWF0aW9uIiwNCiAgICAgICAgICAgICAgICAiUmVzaWRlbnRpYWwgSEQiLA0KICAgICAgICAgICAgICAgICJSZXNpZGVudGlhbCBMRCIsDQogICAgICAgICAgICAgICAgIlRpbWJlciIsDQogICAgICAgICAgICAgICAgIldldGxhbmRzIikpKQ0KICAgICAgICAgIA0KICAgICAgICAgICMgMy4gbW9kZWwNCiAgICAgICAgICBzZXRDIDwtIG1vZGVsKGFjY3VtQykNCg0KICAgICAgICAgIGRmMSA8LSBBX21hdHJpeF8yDQogICAgICAgICAgIyBkZiA8LSBCX21hdHJpeA0KICAgICAgICAgICMgZGYgPC0gQ19tYXRyaXgNCiAgICAgICAgICANCiAgICAgICAgICBuYW1lcyhkZjEpWzc6MTA2XSA8LSBwYXN0ZTAoIlYiLHNlcSgxOjEwMCkpDQogICAgICAgICAgZGYxJG1hcGlkID0gbWFwaWQNCiAgICAgICAgICANCiAgICAgICAgICAjIDIuIGFjY3VtDQogICAgICAgICAgYWNjdW1BIDwtIGdlbmVyYXRlLm9uYS5vYmplY3QoDQogICAgICAgICAgICBkZjEsDQogICAgICAgICAgICB1bml0LmNvbCA9IGRmMVssMTo3XSwNCiAgICAgICAgICAgIG1ldGEuY29sID0gZGYxWywxOjddLA0KICAgICAgICAgICAgY29kZXMgPSBhcy52ZWN0b3IoDQogICAgICAgICAgICAgIGMoIkNvbW1lcmNpYWwiLA0KICAgICAgICAgICAgICAgICJDb25zZXJ2YXRpb25fbHUiLA0KICAgICAgICAgICAgICAgICMgIkNvbnNlcnZhdGlvbiIsDQogICAgICAgICAgICAgICAgIkNyb3BsYW5kIiwNCiAgICAgICAgICAgICAgICAiSW5kdXN0cmlhbCIsDQogICAgICAgICAgICAgICAgIyAiTGltaXRlZCBVc2UiLA0KICAgICAgICAgICAgICAgICJQYXN0dXJlIiwNCiAgICAgICAgICAgICAgICAiUmVjcmVhdGlvbiIsDQogICAgICAgICAgICAgICAgIlJlc2lkZW50aWFsIEhEIiwNCiAgICAgICAgICAgICAgICAiUmVzaWRlbnRpYWwgTEQiLA0KICAgICAgICAgICAgICAgICJUaW1iZXIiLA0KICAgICAgICAgICAgICAgICJXZXRsYW5kcyIpKSkNCiAgICAgICAgICANCiAgICAgICAgICAjIDMuIG1vZGVsDQogICAgICAgICAgc2V0QSA8LSBtb2RlbChhY2N1bUEpDQogICAgICAgICAgDQogICAgICAgICAgc2V0PW1vZGVsKGFjY3VtQywgcm90YXRpb24uc2V0ID0gc2V0QSRyb3RhdGlvbikNCiAgICAgICAgICANCiAgICAgICAgICBub2RlX3NpemVfbXVsdGlwbGllciA9IDAuMg0KICAgICAgICAgIG5vZGVfcG9zaXRpb25fbXVsdGlwbGllciA9IDEuMA0KICAgICAgICAgIGVkZ2Vfc2l6ZV9tdWx0aXBsaWVyID0gMC4yDQogICAgICAgICAgcG9pbnRfcG9zaXRpb25fbXVsdGlwbGllciA9IDEuMA0KICAgICAgICAgIGVkZ2VfYXJyb3dfc2F0dXJhdGlvbl9tdWx0aXBsaWVyID0gMS4wDQogICAgICAgICAgDQogICAgICAgICAgQSA9IHNldEEkcG9pbnRzW0VOQV9ESVJFQ1RJT049PSAncmVzcG9uc2UnXQ0KICAgICAgICAgIHVzZXJfbmFtZXMgPC0gdW5pcXVlKENfbWF0cml4JHVzZXJfbmFtZSkNCiAgICAgICAgICBuIDwtIGxlbmd0aCh1c2VyX25hbWVzKQ0KICAgICAgICAgIGNvbG9yc19zZWxlY3RlZCA8LSBkaXN0aW5jdENvbG9yUGFsZXR0ZShuKQ0KICAgICAgICAgIHNlbGVjdGVkX3VzZXJzIDwtIHVzZXJfbmFtZXNbYygyLDMsNCw2KV0gIyBmb3IgMzAxNzYxMw0KICAgICAgICAgIG9uYV9wbG90KCkNCiAgICAgICAgICAjIHBsb3RseTo6ZXhwb3J0KGZpbGUgPSBwYXN0ZTAoInBsb3RzLyIsIG1hcGlkLCAiL3Bsb3RfIiwgaTEsIGkyLCBpMywgaTQsIGk1LCIucG5nIikpDQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCn0NCmBgYA0KDQo=